package jinyilw.tools.net.dev;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class TCPServer extends BaseServer
{
	private final ServerSocketChannel server;
	private final Selector selector;

	public TCPServer(int port) throws IOException
	{
		this(new InetSocketAddress(port));
	}

	public TCPServer(SocketAddress host) throws IOException
	{
		server = ServerSocketChannel.open();
		server.socket().bind(host);
		server.configureBlocking(false);
		selector = Selector.open();
		server.register(selector, SelectionKey.OP_ACCEPT);
	}

	@Override
	public void update(long elapsedTime) throws IOException
	{
		super.update(elapsedTime);
		selector.select();
		Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
		while (iterator.hasNext())
		{
			SelectionKey key = iterator.next();
			iterator.remove();
			if (key.isAcceptable())
			{
				SocketChannel client = server.accept();
				TCPClient tcpClient = new TCPClient(this, client, selector);
				addConnectingClient(tcpClient);
			} else if (key.isReadable())
			{
				TCPClient client = (TCPClient) key.attachment();
				try
				{
					client.read();
				} catch (IOException ex)
				{
					key.cancel();
					removeClient(client);
				}
			}
		}
	}

	@Override
	protected void disconnectImpl() throws IOException
	{
		server.close();
	}

	@Override
	public String getDetail()
	{
		return server.socket().getLocalSocketAddress().toString();
	}

	public int getAllClientsNumber()
	{
		return getClients().length + getConnectingClients().length;
	}
}
